package cn.lcfms.app.process.service;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.stereotype.Service;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;


@Service
public class ProcessEditService {

	/**
	 * 改变开始事件
	 * @param xml 
	 * @param eventType 要找的节点
	 * @param id  要找的id
	 * @param add 新变化的类型
	 * @return
	 * @throws IOException
	 * @throws DocumentException
	 */
	@SuppressWarnings("unchecked")
	public String changeStartEvent(String xml,String id,String add)throws IOException, DocumentException{
		 Document document = DocumentHelper.parseText(xml); 
		 Element element=document.getRootElement();
		 Element process = element.element("process");
		 Iterator<Element> iterator = process.elementIterator("startEvent");
		 while(iterator.hasNext()) {
			 Element next = iterator.next();
			 String _id=next.attributeValue("id");
			 if(_id.equals(id)) {
				 next.clearContent();				 
				 if(!add.equals("")) {
					 Element a = next.addElement(add);
					 a.addText("");						
				 }					
			 }
		 }
		 String asXML = document.asXML();
		 return asXML;
	}
	
	/**
	 * 改变结束事件
	 * @param xml 
	 * @param eventType 要找的节点
	 * @param id  要找的id
	 * @param add 新变化的类型
	 * @return
	 * @throws IOException
	 * @throws DocumentException
	 */
	@SuppressWarnings("unchecked")
	public String changeEndEvent(String xml,String id,String add)throws IOException, DocumentException{
		 Document document = DocumentHelper.parseText(xml); 
		 Element element=document.getRootElement();
		 Element process = element.element("process");
		 Iterator<Element> iterator = process.elementIterator("endEvent");
		 while(iterator.hasNext()) {
			 Element next = iterator.next();
			 String _id=next.attributeValue("id");
			 if(_id.equals(id)) {
				 next.clearContent();				 
				 if(!add.equals("")) {
					 Element a = next.addElement(add);
					 a.addText("");						
				 }					
			 }
		 }
		 String asXML = document.asXML();
		 return asXML;
	}
	
	/**
	 * 修改属性
	 * @param xml
	 * @param shapeId
	 * @param name
	 * @param value
	 * @return
	 * @throws DocumentException
	 */
	@SuppressWarnings("unchecked")
	public String changeAttribute(String xml, String id, String type,String attribute, String value) throws DocumentException {
		 Document document = DocumentHelper.parseText(xml); 
		 Element element=document.getRootElement();
		 Element process = element.element("process");
		 Iterator<Element> iterator = process.elementIterator(type);
		 while(iterator.hasNext()) {
			 Element next = iterator.next();
			 String _id=this.attribute(next, "id");
			 if(_id.equals(id)) {
				if(attribute.indexOf(":")!=-1) {
					String s=attribute.substring(attribute.indexOf(":")+1);
					Attribute a = next.attribute(s);
					if(null==a) {
						next.addAttribute(attribute, value);
					}else {
						a.setValue(value);
					}
				}else {
					next.addAttribute(attribute, value);
				}
			 }
		 }
		 String asXML = document.asXML();
		 return asXML;
	}
	
	@SuppressWarnings("unchecked")
	public String changeChildAttribute(String xml, String id, String type, String act, String value) throws DocumentException {
		Document document = DocumentHelper.parseText(xml); 
		Element element=document.getRootElement();
		Element process = element.element("process");	
		Iterator<Element> iterator = process.elementIterator(type);
		 while(iterator.hasNext()) {
			 Element next = iterator.next();
			 String _id=this.attribute(next, "id");
			 if(_id.equals(id)) {
				String[] split = act.split(",");	
				Element end = next.element(split[0]); 
				if(split[1].indexOf(":")!=-1) {
					String s=split[1].substring(split[1].indexOf(":")+1);
					Attribute a = end.attribute(s);
					if(null==a) {
						end.addAttribute(split[1], value);
					}else {
						a.setValue(value);
					}
				}else {
					end.addAttribute(split[1], value);
				}		
			 }
		 }
		 String asXML = document.asXML();
		 return asXML;
	}
	/**
	 * 修改流程名称
	 * @param xml
	 * @param value
	 * @return
	 * @throws DocumentException
	 */
	public String changeProcessName(String xml,String value) throws DocumentException {
		 Document document = DocumentHelper.parseText(xml); 
		 Element element=document.getRootElement();
		 Element process = element.element("process");
		 process.addAttribute("name", value);
		 String asXML = document.asXML();
		 return asXML;
	}
	/**
	 * 修改命名空间
	 * @param xml
	 * @param value
	 * @return
	 * @throws DocumentException 
	 */
	public String changeNamespace(String xml, String value) throws DocumentException {
		Document document = DocumentHelper.parseText(xml); 		
		Element element=document.getRootElement();
		element.addAttribute("targetNamespace", value);
		String asXML = document.asXML();
		return asXML;
	}
	/**
	 * 修改文档
	 * @param xml
	 * @param value
	 * @return
	 * @throws DocumentException
	 */
	@SuppressWarnings("unchecked")
	public String changeDocument(String xml,String type,String id,String value) throws DocumentException {
		Document document = DocumentHelper.parseText(xml); 		
		Element element=document.getRootElement();
		Element process = element.element("process");
		if(type.equals("process")) {
			Element d1 = process.element("documentation");
			d1.setText(value);
		}else {
			Iterator<Element> iterator = process.elementIterator(type);
			while(iterator.hasNext()) {
				 Element next = iterator.next();
				 String _id=attribute(next, "id");
				 if(_id.equals(id)) {
					 Element d = next.element("documentation");
					 if(null==d) {
						 d = next.addElement("documentation");
					 }
					 d.setText(value);
				 }
			 }
		}
		String asXML = document.asXML();
		return asXML;
	}
	/**
	 * 开始导入bpmn文件,获取基本参数
	 * @param xml
	 * @return
	 * @throws DocumentException
	 */
	public JSONObject getBaseData(String xml) throws DocumentException {
		JSONObject object=new JSONObject();
		Document document = DocumentHelper.parseText(xml); 		
		Element element=document.getRootElement();
		String namespace = element.attributeValue("targetNamespace");
		Element process = element.element("process");
		String _id=process.attributeValue("id");
		String isExecutable=process.attributeValue("isExecutable");
		String name=attribute(process, "name");
		Element docment = process.element("documentation");
		if(null!=docment) {
			String text = docment.getText();
			object.put("documentation", text);
		}
		object.put("id", _id);
		object.put("name", name);
		object.put("isExecutable", isExecutable);
		object.put("type", "process");
		object.put("namespace", namespace);
		return object;
	}
	
	/**
	 * 根据id获取节点参数
	 * @param xml
	 * @param id
	 * @return
	 * @throws DocumentException
	 */
	@SuppressWarnings("unchecked")
	public JSONObject getDataById(String xml,String id) throws DocumentException {
		Document document = DocumentHelper.parseText(xml); 
		Element element=document.getRootElement();
		Element process = element.element("process");
		Iterator<Element> iterator = process.elementIterator();
		JSONObject object=new JSONObject();
		object.put("id", id);
		while(iterator.hasNext()) {
			 Element next = iterator.next();
			 String _id=attribute(next,"id");
			 if(_id.equals(id)) {				  
				 String bpmn = next.getName();
				 object.put("type", bpmn);
				 List<Attribute> attris = next.attributes();
				 for(Attribute att:attris) {
					 if(!att.getName().equals("exclusive")) {
						 object.put("exclusive", "true");
					 }
					 object.put(att.getName(), att.getValue());
				 }
				 Element d = next.element("documentation");
				 if(null!=d) {
					 object.put("documentation", d.getText());
				 }
				 Element x = next.element("extensionElements");
				 if(null!=x) {
					List<Element> form = x.elements("formProperty");
					JSONArray a=new JSONArray();
					for(int i=0;i<form.size();i++) {
						JSONObject o=new JSONObject();
						Element f=form.get(i);
						o.put("id", attribute(f, "id"));
						o.put("name", attribute(f, "name"));
						o.put("type", attribute(f, "type"));
						String required=attribute(f, "required").equals("")?"false":attribute(f, "required");					
						o.put("required",required);
						String readable=attribute(f, "readable").equals("")?"false":attribute(f, "readable");
						o.put("readable", readable);
						String writeable=attribute(f, "writeable").equals("")?"false":attribute(f, "writeable");
						o.put("writeable", writeable);				
						o.put("datePattern", attribute(f, "datePattern"));				
						o.put("default", attribute(f, "default"));
						o.put("expression", attribute(f, "expression"));
						o.put("variable", attribute(f, "variable"));
						List<Element> e = f.elements("value");
						if(null!=e && e.size()>0) {
							JSONArray ar=new JSONArray();
							for(int j=0;j<e.size();j++) {
								JSONObject ob=new JSONObject();
								ob.put("id", e.get(j).attributeValue("id"));
								ob.put("name", e.get(j).attributeValue("name"));
								ar.add(ob);
							}
							o.put("value", ar);
						}
						a.add(o);
					}
					object.put("form", a.toString());
				 }else {
					object.put("form", "[]");
				 }
				 if(bpmn.equals("startEvent")) {
					 Element e1=next.element("timerEventDefinition");
					 Element e2=next.element("messageEventDefinition");
					 Element e3=next.element("errorEventDefinition");
					 Element e4=next.element("signalEventDefinition");
					 if(null!=e1) {
						 object.put("startType", "timerEventDefinition");
					 }else if(null!=e2) {
						 object.put("startType", "messageEventDefinition");
					 }else if(null!=e3) {
						 object.put("startType", "errorEventDefinition");
					 }else if(null!=e4) {
						 object.put("startType", "signalEventDefinition");
					 }else {
						 object.put("startType", "");
					 }
					 String initiator = attribute(next, "initiator");
					 object.put("initiator", initiator);
					 String formKey = attribute(next, "formKey");
					 object.put("formKey", formKey);
				 }
				 if(bpmn.equals("serviceTask") && object.containsKey("type") && object.getString("type").equals("mail")) {
					 object.put("type", "mailTask");
				 }
				 if(bpmn.equals("sequenceFlow")) {
					 Element e1=next.element("conditionExpression");
					 if(null!=e1) {
						 String text = e1.getText();
						 object.put("conditionExpression", text);
					 }		
				 }
				 if(bpmn.equals("endEvent")) {
					 Element e1=next.element("errorEventDefinition");
					 Element e2=next.element("terminateEventDefinition");
					 Element e3=next.element("cancelEventDefinition");
					 if(null!=e1) {
						 object.put("endType", "errorEventDefinition");
						 String errorRef = e1.attributeValue("errorRef");
						 object.put("errorRef", errorRef);
					 }else if(null!=e2) {
						 object.put("endType", "terminateEventDefinition");
					 }else if(null!=e3) {
						 object.put("endType", "cancelEventDefinition");
					 }else {
						 object.put("endType", "");
					 }
				 }
				 if(bpmn.equals("intermediateCatchEvent") || bpmn.equals("intermediateThrowEvent")) {
					 if(bpmn.equals("intermediateCatchEvent") && null!=next.element("signalEventDefinition")) {
						 object.put("intermediateType", "SignalCatchEvent");
					 }else if(bpmn.equals("intermediateThrowEvent") && null!=next.element("signalEventDefinition")) {
						 object.put("intermediateType", "SignalThrowEvent");
					 }else if(bpmn.equals("intermediateCatchEvent") && null!=next.element("timerEventDefinition")) {
						 object.put("intermediateType", "TimerCatchEvent");
					 }else if(bpmn.equals("intermediateCatchEvent") && null!=next.element("messageEventDefinition")) {
						 object.put("intermediateType", "MessageCatchEvent");
					 }else if(bpmn.equals("intermediateThrowEvent") && null!=next.element("compensateEventDefinition")) {
						 object.put("intermediateType", "CompensationThrowingEvent");
					 }else {
						 object.put("intermediateType", "NoneThrowEvent");
					 }
				 }
			 }
		 }
		return object;
	}
	
	private String attribute(Element element,String attribute) {
		 String value=element.attributeValue(attribute);
		 if(null==value) {
			 return "";
		 }else {
			 return value;
		 }
	}
	

	@SuppressWarnings("unchecked")
	public String saveForm(String xml, String type, String id, String value) throws DocumentException {
		Document document = DocumentHelper.parseText(xml); 
		Element element=document.getRootElement();
		Element process = element.element("process");
		Iterator<Element> iterator = process.elementIterator(type);
		 while(iterator.hasNext()) {
			 Element next = iterator.next();
			 String _id=this.attribute(next, "id");
			 if(_id.equals(id)) {
				 Element e = next.element("extensionElements");
				 if(null==e) {
					 e=next.addElement("extensionElements");
				 }
				 List<Element> ls = e.elements("formProperty");
				 if(ls.size()>0) {
					 for(Element l:ls) {
						 e.remove(l);
					 }
				 }
				 JSONArray array=JSONArray.fromObject(value);
				 for(int i=0;i<array.size();i++) {
					 Element f=e.addElement("activiti:formProperty");
					 String id_=array.getJSONObject(i).getString("id");
					 String name=array.getJSONObject(i).getString("name");
					 String _type=array.getJSONObject(i).getString("type");
					 String datePattern=array.getJSONObject(i).getString("datePattern");
					 String expression=array.getJSONObject(i).getString("expression");
					 String variable=array.getJSONObject(i).getString("variable");
					 String _default=array.getJSONObject(i).getString("default");
					 String readable=array.getJSONObject(i).getString("readable");
					 String writeable=array.getJSONObject(i).getString("writeable");
					 String required=array.getJSONObject(i).getString("required");					 										 
					 addAttribute(f,"id",id_);
					 addAttribute(f,"name",name);
					 addAttribute(f,"type",_type);
					 if(_type.equals("date")) {
						 addAttribute(f,"datePattern",datePattern);
					 }
					 addAttribute(f,"expression",expression);
					 addAttribute(f,"variable",variable);
					 addAttribute(f,"default",_default);
					 addAttribute(f,"readable",readable);
					 addAttribute(f,"writeable",writeable);
					 addAttribute(f,"required",required);
					 if(array.getJSONObject(i).containsKey("value")) {
						 JSONArray _value=array.getJSONObject(i).getJSONArray("value");
						 if(_value.size()>0) {
							 for(int j=0;j<_value.size();j++) {
								 JSONObject o = _value.getJSONObject(j);
								 Element v = f.addElement("activiti:value");
								 v.addAttribute("id", o.getString("id"));
								 v.addAttribute("name", o.getString("name"));
							 }
						 }
					 } 
				 }
			 }
		 }
		 String asXML = document.asXML();
		 return asXML;
	}
	
	private void addAttribute(Element f,String name,String value) {
		if(value.equals("")) {
			return;
		}
		f.addAttribute(name,value);
	}
	
	/**
	 * 修改任务
	 * @param xml
	 * @param id
	 * @param value
	 * @return
	 * @throws DocumentException
	 */
	@SuppressWarnings("unchecked")
	public String changeEventTask(String xml, String id,String value) throws DocumentException {
		Document document = DocumentHelper.parseText(xml); 		
		Element element=document.getRootElement();
		Element process = element.element("process");
		Iterator<Element> iterator = process.elementIterator();
		while(iterator.hasNext()) {
			 Element next = iterator.next();
			 String _id=attribute(next, "id");
			 if(_id.equals(id)) {
				 List<Attribute> a = next.attributes();	
				 Element n;
				 if(value.equals("mailTask")) {					 
					 value="serviceTask";
					 n = process.addElement(value);
					 n.addAttribute("activiti:type", "mail");
				 }else {
					 n = process.addElement(value);
				 }				
				 for(Attribute l : a) {
					if(l.getName().equals("type"))continue;
				    n.addAttribute(l.getName(), l.getValue());
				 }
				 Element d = next.element("documentation");
				 if(null!=d) {
					 Element d1 = n.addElement("documentation");
					 d1.addText(d.getText());
				 }			 
				 process.remove(next);
			 }
		 }			
		String asXML = document.asXML();
		return asXML;
	}
	
	@SuppressWarnings("unchecked")
	public String changeConditionExpression(String xml, String id, String value) throws DocumentException {
		Document document = DocumentHelper.parseText(xml); 		
		Element element=document.getRootElement();
		Element process = element.element("process");	
		Iterator<Element> iterator = process.elementIterator();
		while(iterator.hasNext()) {
			 Element next = iterator.next();
			 String _id=attribute(next, "id");
			 if(_id.equals(id)) {
				 Element e = next.element("conditionExpression");	
				 if(null==e) {
					 if(!value.equals("")) {
						 e=next.addElement("conditionExpression");
						 e.addAttribute("xsi:type", "tFormalExpression");
						 e.addCDATA(value);
					 }				
				 }else {
					 if(value.equals("")) {
						 next.remove(e);
					 }else {
						 e.clearContent();
						 e.addCDATA(value);
					 }				
				 }
			 }
		 }			
		String asXML = document.asXML();
		return asXML;
	}

	@SuppressWarnings("unchecked")
	public String savepermission(String xml, String type, String id, String value) throws DocumentException {
		Document document = DocumentHelper.parseText(xml); 
		Element element=document.getRootElement();
		Element process = element.element("process");
		Iterator<Element> iterator = process.elementIterator(type);
		 while(iterator.hasNext()) {
			 Element next = iterator.next();
			 String _id=this.attribute(next, "id");
			 if(_id.equals(id)) {
				JSONObject object=JSONObject.fromObject(value);
				String admin = object.getString("admin");
				if(null!=admin) {
					Attribute a = next.attribute("candidateUsers");
					if(null==a) {
						next.addAttribute("activiti:candidateUsers", admin);
					}else {
						a.setValue(admin);
					}					
				}
				String group = object.getString("group");
				if(null!=group) {
					Attribute b = next.attribute("candidateGroups");
					if(null==b) {
						next.addAttribute("activiti:candidateGroups", group);
					}else {
						b.setValue(group);
					}					
				}
				String organization = object.getString("organization");
				if(null!=organization) {
					Attribute c = next.attribute("candidateOrganization");
					if(null==c) {
						next.addAttribute("activiti:candidateOrganization", organization);
					}else {
						c.setValue(organization);
					}	
				}
			 }
		 }
		 String asXML = document.asXML();
		 return asXML;
	}
	
	@SuppressWarnings("unchecked")
	public String changeIntermediate(String xml,String id, String value) throws DocumentException {
		Document document = DocumentHelper.parseText(xml); 		
		Element element=document.getRootElement();
		Element process = element.element("process");	
		Iterator<Element> iterator = process.elementIterator();
		while(iterator.hasNext()) {
			 Element next = iterator.next();
			 String _id=attribute(next, "id");
			 if(_id.equals(id)) {
				 Element e=null;
				 if(value.equals("NoneThrowEvent")) {					
					 e = process.addElement("intermediateThrowEvent");					
				 }
				 if(value.equals("SignalCatchEvent")) {
					 e = process.addElement("intermediateCatchEvent");
					 e.addElement("signalEventDefinition");
				 }
				 if(value.equals("SignalThrowEvent")) {
					 e = process.addElement("intermediateThrowEvent");					
					 e.addElement("signalEventDefinition");
				 }
				 if(value.equals("TimerCatchEvent")) {				
					 e = process.addElement("intermediateCatchEvent");					
					 e.addElement("timerEventDefinition");
				 }
				 if(value.equals("MessageCatchEvent")) {				
					 e = process.addElement("intermediateCatchEvent");				
					 e.addElement("messageEventDefinition");
				 }
				 if(value.equals("CompensationThrowingEvent")) {			
					 e = process.addElement("intermediateThrowEvent");					
					 e.addElement("compensateEventDefinition");
				 }
				 Attribute name = next.attribute("name");
				 e.addAttribute("id", id);
				 if(null!=name) {
					 e.addAttribute("name", name.getValue());
				 }
				 Element d = next.element("documentation");
				 if(null!=d) {
					 String text = d.getText();
					 Element ln = e.addElement("documentation");
					 ln.addText(text);
				 }
				 process.remove(next);
			 }
		 }			
		String asXML = document.asXML();
		return asXML;
	}

	
	public static void main(String[] args) throws IOException, DocumentException {
		ProcessEditService ps=new ProcessEditService();
		File f1=new File("D:\\lcfms 6.0\\src\\main\\resources\\process\\test.bpmn");
		String str1 = FileUtils.readFileToString(f1, "utf-8");
		str1=ps.changeEventTask(str1, "callactivity1", "businessRuleTask");
		System.out.println(str1);
		
	}


}
